﻿using System;
using System.Collections.Generic;
using System.Linq;
using Mrsoft.Core;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Text;
using Mrsoft.Common;

namespace Mrsoft.AutoStarter {
    class AccManager {

        #region 多开插件接口
        [DllImport(@".\插件\DKPlugin2.dll", CharSet = CharSet.Ansi)]
        private static extern Int32 StartGame(string lpApplicationRouteAndCmd, string lpCurrentDirectory);
        #endregion

        #region 初始化
        /// <summary>
        /// 账号清单
        /// </summary>
        public List<Account> Accounts = new List<Account>();

        /// <summary>
        /// 从序列化来加载
        /// </summary>
        /// <returns></returns>
        public static AccManager Create() {
            return new AccManager {
                Accounts = Account.GetAccList()
            };
        }
        #endregion

        #region 登陆业务实现部分

        /// <summary>
        /// 保证登陆的状态是唯一态
        /// </summary>
        private readonly object loginObject = new object();

        /// <summary>
        /// 登陆过程线程
        /// </summary>
        /// <param name="obj"></param>
        private void Login(object obj) {
            var acc = obj as Account;
            if (acc == null || string.IsNullOrEmpty(GamePath))
                return;
            lock (loginObject) {
                //MsgListener.CommonMsgShow(acc.username, "开始登陆……");
                //自动登陆程序
                while (true) {
                    //MsgListener.CommonMsgShow(acc.username, "修改配置……");
                    //创建游戏客户端
                    var temPath = Path.Combine(GamePath, "bin");
                    var cmd = string.Format("{0} -fl", Path.Combine(temPath, "game.exe"));
                    //写iniGame_MiBao
                    string iniFile = Path.Combine(GamePath, @"Accounts\System.cfg");
                    if (!string.IsNullOrEmpty(acc.serverArea) && !string.IsNullOrEmpty(acc.serverName)) {
                        NativeMethods.IniWriteValue(iniFile, "Variable", "Login_Area", acc.serverArea);
                        NativeMethods.IniWriteValue(iniFile, "Variable", "Login_Server", acc.serverName);
                    }
                    NativeMethods.IniWriteValue(iniFile, "Variable", "Account_LogonType", "2");
                    var mb = string.IsNullOrEmpty(acc.mbId) ? "0" : "1";
                    NativeMethods.IniWriteValue(iniFile, "Variable", "Game_MiBao", mb);
                    var dwProcessId = StartGame(cmd, temPath);
                    if (dwProcessId == 0) { continue; }
                    Thread.Sleep(15000);
                    Process p = new Process();
                    try {
                        p = Process.GetProcessById(dwProcessId);
                        while (p.MainWindowHandle == IntPtr.Zero) {
                            Thread.Sleep(500);
                            if (p.HasExited) { break; }
                        }
                        Thread.Sleep(3000);
                        //登陆处理
                        if (!p.HasExited && LoginPageDeal(p, acc)) {
                            var start = DateTime.Now;
                            while (true) {
                                //验证登陆结果
                                var name = NativeMethods.Rs(dwProcessId,
                                    DirectDealGame.Data.JS,
                                    DirectDealGame.Data.JS_OFF_1,
                                    DirectDealGame.Data.JS_OFF_2,
                                    DirectDealGame.Data.JS_OFF_3,
                                    DirectDealGame.Data.JS_NAME);
                                if (!string.IsNullOrEmpty(name)) {
                                    if (string.IsNullOrEmpty(acc.charaterName) || acc.charaterName != name) {
                                        //更新用户名
                                        acc.charaterName = name;
                                        acc.Update();
                                    }
                                    //MsgListener.CommonMsgShow(acc.username, "完成登陆,角色账号为:" + acc.charaterName);
                                    return; //结束了
                                }
                                if ((DateTime.Now - start).TotalSeconds > 120) {
                                    //MsgListener.CommonMsgShow(acc.username, "登陆校验未能完成，重新登陆");
                                    p.Kill();
                                    break;
                                }
                                Thread.Sleep(500);
                            }
                        }
                    }
                    catch (Exception ex) {
                        MsgListener.CommonMsgShow("登陆异常", ex.Message);
                        p.Kill();
                    }
                }
            }
        }

        /// <summary>
        /// 登陆处理
        /// </summary>
        /// <param name="p">游戏线程</param>
        /// <param name="acc">账号信息</param>
        /// <returns>登陆结果</returns>
        private bool LoginPageDeal(Process p, Account acc) {
            int hwnd = p.MainWindowHandle.ToInt32();
            //不显示错误
            var dm = new DmLibary(hwnd, false, true);
            int x1, y1;
            DateTime start = DateTime.Now;
            MsgListener.CommonMsgShow(acc.username, "转到登陆页面");
            while (!dm.DmRcWord("登陆页面", "c9ff01-00ffff", out x1, out y1)) {
                dm.DmKeyPress("enter");
                Thread.Sleep(1000);
                if (p.HasExited)
                    return false;
                if ((DateTime.Now - start).TotalSeconds > 120) {
                    p.Kill();
                    //MsgListener.CommonMsgShow(acc.username, "等待时间过长关闭重开游戏");
                }
            }
            //MsgListener.CommonMsgShow(acc.username, "输入密码");

            dm.SendString(hwnd, acc.username);
            dm.DmKeyPress("enter");
            Thread.Sleep(500);
            dm.SendString(hwnd, acc.password);
            dm.DmKeyPress("enter");
            Thread.Sleep(500);
            //登陆完成 登陆确认
            start = DateTime.Now;
            //MsgListener.CommonMsgShow(acc.username, "等待进入登陆页面");
            Password.SecretCard mibao = null;
            while (!dm.DmRcWord("登陆确定", "fdeb78-00ffff", out x1, out y1)) {
                Thread.Sleep(1000);
                if (p.HasExited)
                    return false;
                //检查是否需要填写 密保卡
                if (!string.IsNullOrEmpty(acc.mbId)) {
                    mibao = mibao ?? Password.SecretCardDAL.GetSecretCardById(acc.mbId);
                    int x2, y2;
                    if (dm.DmRcWord("密保标志", "fff263-0fffff", out x2, out y2)) {
                        var str = dm.Ocr(x2, y2, x2 + 160, y2 + 124, "fff263-0fffff", 1.0);
                        str = str.Replace("时辰识别", "").Replace("，", "").Replace(",", "").Replace("密保标志", "");
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < 3; i++) {
                            sb.Append(mibao.GetValue(str.Substring(1 + 2 * i, 1), str.Substring(2 * i, 1)));
                        }
                        Common.MsgListener.CommonMsgShow(acc.username, string.Format("密保识别结果为{0}", sb.ToString()));
                        dm.SendString(hwnd, sb.ToString());
                        dm.DmKeyPress("enter");
                        Thread.Sleep(1000);
                    }
                }

                //检查是否因为上次登录错误导致了要输入验证码
                if (dm.DmRcWord("登陆验证接口", "ffffff-000000", out x1, out y1)) {
                    if (LoginYanZheng(dm, x1, y1, hwnd))
                        start = DateTime.Now;
                    Thread.Sleep(2000);
                }

                if ((DateTime.Now - start).TotalSeconds > 100) {
                    p.Kill();
                    //MsgListener.CommonMsgShow(acc.username, "等待时间过长关闭重开游戏");
                }
            }
            start = DateTime.Now;
            //MsgListener.CommonMsgShow(acc.username, "打开登陆验证");
            //发现登陆验证码
            while (!dm.DmRcWord("登陆验证接口", "ffffff-00ffff", out x1, out y1)) {
                dm.DmKeyPress("enter");
                Thread.Sleep(1000);
                if (p.HasExited)
                    return false;
                if ((DateTime.Now - start).TotalSeconds > 60) {
                    p.Kill();
                    //MsgListener.CommonMsgShow(acc.username, "等待时间过长关闭重开游戏");
                }
            }
            LoginYanZheng(dm, x1, y1, hwnd);
            dm.Dispose();
            return true;
        }

        /// <summary>
        /// 验证码处理
        /// </summary>
        /// <param name="dm"></param>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="hwnd"></param>
        /// <returns></returns>
        private bool LoginYanZheng(DmLibary dm, int x1, int y1, int hwnd) {

            var dtDir = string.Format(@"{0}\user\答题图片\", Directory.GetCurrentDirectory());

            if (!Directory.Exists(dtDir)) {
                Directory.CreateDirectory(dtDir);
            }

            string imagefile = string.Format(@"{0}{1}.jpg", dtDir, DateTime.Now.ToBinary().ToString());

            dm.CaptureJpg(x1, y1 - 20, x1 + 390, y1 + 80, imagefile);

            var datiModel = new DatiModel() {
                ImageFullPath = imagefile,
                Timeout = 120,
                QuestinType = 2000,
                TipsMessage = "0-9纯数字"
            };

            var answer = DatiManager.Answer(datiModel);

            if (answer.OK) {
                dm.SendString(hwnd, answer.Message);
                Thread.Sleep(500);
                dm.DmKeyPress("enter");
            }
            else {
                MsgListener.CommonMsgShow("[答题系统]", answer.Message);
            }

            if (File.Exists(imagefile))
                File.Delete(imagefile);
            return answer.OK;
        }

        #endregion

        #region 增删改查

        /// <summary>
        /// 添加新用户
        /// </summary>
        /// <param name="acc"></param>
        /// <returns></returns>
        public bool InsertAccount(Account acc) {
            //添加一个账户
            if (Accounts.Count(t => t.username == acc.username) == 0) {
                Accounts.Add(acc);
                acc.Insert();
            }
            return false;
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public bool DeleteAccout(string userName) {
            for (int i = 0; i < Accounts.Count; i++) {
                if (Accounts[i].username == userName) {
                    if (Accounts[i].Delete())
                        Accounts.RemoveAt(i);
                }
            }
            return true;
        }

        /// <summary>
        /// 通过账号名字来获取账号信息
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public Account GetAccountByUserName(string userName) {
            var list = Accounts.Where(t => t.username == userName);
            foreach (var acc in list) {
                return acc;
            }
            return null;
        }

        #endregion

        #region 游戏路径

        internal readonly static Config<string> GameDirectory = new Config<string>("./common.cfg", "autostart/gamepath", "");

        public string GamePath {
            get { return GameDirectory.Value; }
        }
        #endregion

        /// <summary>
        /// 开启游戏
        /// </summary>
        public void StartGame() {
            if (!string.IsNullOrEmpty(GamePath)) {
                var path = Path.Combine(GamePath, "bin");
                var cmd = string.Format("{0} -fl", Path.Combine(path, "game.exe"));
                StartGame(cmd, path);
            }
        }

        /// <summary>
        /// 启动自动登陆
        /// </summary>
        /// <param name="acc"></param>
        public void Login(Account acc) {
            new Task(Login, acc).Start();
        }

    }
}
